home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / askrunlevel / askrunlevel.c < prev    next >
C/C++ Source or Header  |  1996-08-03  |  10KB  |  332 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdarg.h>
  5. #include <unistd.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <limits.h>
  9. #include "askrunlevel.h"
  10. #include "internal.h"
  11. #include <ncurses/curses.h>
  12. #include "../misc/misc.h"
  13. #include "../xconf/xconf.h"
  14. #include "../netconf/netconf.h"
  15. #include "../userconf/userconf.h"
  16. #include "../main/main.h"
  17. #include "../fstab/fstab.h"
  18. #include "../paths.h"
  19. #include "askrunlevel.m"
  20.  
  21. static HELP_FILE help_askrun (HELP_ASKRUN,"intro");
  22. static HELP_FILE help_boot (HELP_ASKRUN,"boot");
  23.  
  24.  
  25. /* #Specification: askrunlevel / intro
  26.     When linux boot, it start /sbin/init which does some
  27.     basic initialisation, then try to jump to its default
  28.     run level. If this default run level is not defined and
  29.     /sbin/askrunlevel do exist, then it is execute.
  30.  
  31.     The purpose of this program is to let the user select the
  32.     run level in a meaningful way. Instead of numbers, it
  33.     present a menu of configuration useful for a workstation.
  34.     Also, askrunlevel try to validate which configuration are
  35.     possible. There is no need to ask the user if he want to
  36.     start X automatically (using xdm) unless X has been configured.
  37.  
  38.     To make it easy for the user, askrunlevel act also has a first
  39.     time configuration utility. So if a configuration do not exist
  40.     it let the user configure it right away. No need to boot twice
  41.     (once to configure, and once to activate the configuration).
  42.  
  43.     If the user do not select anything in a specific time, the
  44.     default run level is activate.
  45.  
  46.     The future will tell if this is true...
  47. */
  48.  
  49. static void askrunlevel_saynographic(const char *status_graphic)
  50. {
  51.     xconf_error (MSG_U(E_GRAPH,"Can't do this\n"
  52.         "because the Graphic mode is not yet\n"
  53.         "configured\n\n%s"),status_graphic);
  54. }
  55. static void askrunlevel_saynographic_net(
  56.     char *status_graphic,
  57.     char *status_net)
  58. {
  59.     xconf_error (MSG_U(E_GRAPHNET,"Can't do this\n"
  60.         "because the Graphic mode\n"
  61.         "and the Networking are not yet\n"
  62.         "configured\n\n%s\n\n%s"),status_graphic,status_net);
  63. }
  64. static void askrunlevel_saynonet(char *status_net)
  65. {
  66.     xconf_error (MSG_U(E_NET,"Can't do this\n"
  67.         "because the Networking is not yet\n"
  68.         "configured\n\n%s"),status_net);
  69. }
  70.  
  71. /*
  72.     Activate the timeout only if the system is freshly start.
  73.     If uptime is old enough, it means askrunlevel was called
  74.     after the user explicitly told init to do so, so the timeout
  75.     feature is not useful here.
  76.  
  77.     Return the timeout value (in seconds) or 0.
  78. */
  79. static int askrunlevel_enabletimeout(ASK_PARM &parm)
  80. {
  81.     FILE *fin = xconf_fopen ("/proc/uptime","r");
  82.     int timeout = 0;
  83.     // We assume that if /proc/uptime is not available, better
  84.     // play safe and disable the timeout feature.
  85.     if (fin != NULL){
  86.         /* #Specification: askrunlevel / automatic booting / timeout
  87.             linuxconf will automaticly boot the system into
  88.             the default runlevel (as configured) only
  89.             if it is called at boot time (when called as /sbin/askrunlevel).
  90.  
  91.             There is two possibilities: Either the boot
  92.             was normal (ie. fairly fast) or fairly slow
  93.             (the system had to do a fsck after a crash).
  94.             In the first case, it will boot as configured
  95.             after the specified timeout.
  96.  
  97.             If the system took more than 60 seconds to boot
  98.             it will still boot by itself, but will selected
  99.             a timeout of one minute. The system will
  100.             also activate the bell.
  101.  
  102.             This is to catch the attention of the
  103.             operator.
  104.         */
  105.         long uptime;
  106.         if (fscanf (fin,"%ld",&uptime)==1){
  107.             timeout = parm.timeout;
  108.             if(uptime > 60 && timeout != 0){
  109.                 timeout = 60;
  110.                 for (int i=0; i<2; i++){
  111.                     putchar ('\a');
  112.                     fflush (stdout);
  113.                     sleep(1);
  114.                 }
  115.             }
  116.             dialog_settimeout (timeout,MENU_ESCAPE,false);
  117.         }else{
  118.             xconf_error (MSG_U(E_PROCUPTIME,"Can't parse /proc/uptime\n"));
  119.         }
  120.         fclose (fin);
  121.     }
  122.     return timeout;
  123. }
  124.  
  125. /*
  126.     Configure the default runlevel.
  127. */
  128. void askrunlevel_config()
  129. {
  130.     char status_graphic[2000];
  131.     int graphic_ok = xconf_xok(status_graphic);
  132.     char status_net[2000];
  133.     int net_ok = netconf_netok(status_net) != NULL;
  134.     int choice = 0;
  135.     while (1){
  136.         RUNLEVELS runlevels (graphic_ok,net_ok);
  137.         static const char *lilo_conf = MSG_U(M_LILO,"LILO (Linux boot loader)");
  138.         static const char *lilo_default = MSG_U(M_DEFLILO,"default boot configuration");
  139.         static const char *lilo_confaddany = MSG_U(M_NEWKERN,"a new kernel");
  140.         static const char *lilo_confaddcompil = MSG_U(M_COMPILED,"a kernel you have compiled");
  141.         static const char *config_mode  = MSG_U(M_DEFBOOT,"default boot mode");
  142.         static const char *config_define = MSG_U(M_RUNLEVELS,"runlevels");
  143.  
  144.         static const char *menuopt[]={
  145.             MSG_U(M_CONFIG,"Configure"),    lilo_conf,
  146.             MSG_U(M_CHANGE,"Change"),    lilo_default,
  147.             MSG_U(M_ADDLILO,"Add to LILO"),    lilo_confaddany,
  148.             " ",                        lilo_confaddcompil,
  149.             "-",                        "",
  150.             " ",                        config_mode,
  151.             MSG_U(M_DEFINE,"Define"),    config_define,
  152.             NULL
  153.         };
  154.         MENU_STATUS code = xconf_menu (
  155.             MSG_U(T_BOOTCONF,"Boot configuration")
  156.             ,MSG_U(I_BOOTCONF,"You are allowed to define the default\n"
  157.              "boot mode of this computer")
  158.             ,help_boot
  159.             ,menuopt,choice);
  160.         if (code != MENU_OK){
  161.             break;
  162.         }else{
  163.             const char *key = menuopt[choice*2+1];
  164.             if (key == config_mode){
  165.                 runlevels.config();
  166.             }else if (key == lilo_conf){
  167.                 lilo_edit();
  168.             }else if (key == lilo_default){
  169.                 lilo_setdefault();
  170.             }else if (key == lilo_confaddany){
  171.                 lilo_addany();
  172.             }else if (key == lilo_confaddcompil){
  173.                 lilo_addcompil();
  174.             }else if(key == config_define){
  175.                 runlevels.define();
  176.             }
  177.         }
  178.     }
  179. }
  180.  
  181. static int askrunlevel_chkterm ()
  182. {
  183.     int ret = -1;
  184.     const char *pt = getenv ("TERM");
  185.     if (pt != NULL){
  186.         char path[PATH_MAX];
  187.         sprintf (path,"/usr/lib/terminfo/%c/%s",*pt,pt);
  188.         if (file_exist (path)) ret = 0;
  189.     }
  190.     return ret;
  191. }
  192.  
  193. static void askrunlevel_setterm()
  194. {
  195.     /* #Specification: askrunlevel / terminal type
  196.         askrunlevel is called very early at boot time. At this
  197.         time the TERM environnement variable is set directly by
  198.         the kernel (it can be overriden by init I think). In
  199.         kernel 1.2.x, it is generally set to "con80x25". In newer
  200.         kernel, it is set to "linux".
  201.  
  202.         Many (Most) system out there simply do not have a
  203.         definition in /usr/lib/terminfo for such a TERM type.
  204.  
  205.         When starting askrunlevel, we check if the TERM variable
  206.         do point to something in /usr/lib/terminfo. If not, TERM
  207.         is silently set to "linux". If linux is not defined, it
  208.         is set to "console". This should cover most cases.
  209.     */
  210.     if (askrunlevel_chkterm()==-1){
  211.         putenv ("TERM=linux");
  212.         if (askrunlevel_chkterm()==-1){
  213.             putenv ("TERM=console");
  214.             if (askrunlevel_chkterm()==-1){
  215.                 RUNLEVELS runlevels(0,0);
  216.                 runlevels.setlevel (4);
  217.                 printf (MSG_U(E_TERMINFO
  218.                     ,"No valid TERM definition\n"
  219.                      "probably caused by an improperly installed\n"
  220.                      "terminfo database.\n"));
  221.                 exit (-1);
  222.             }
  223.         }
  224.     }
  225. }
  226.  
  227. int askrunlevel_main (int , char *[])
  228. {
  229.     modules_dummy();    // Just to ease the link
  230.     askrunlevel_setterm();
  231.     /* Specification: askrunlevel / principal
  232.         The user must select one of these choice
  233.  
  234.             Start in graphic mode
  235.                      graphic mode and network
  236.                      text mode
  237.                      text mode and network
  238.                      maintenance mode
  239.             Set the default boot mode
  240.             Set the timeout value
  241.     */
  242.     ASK_PARM parm;
  243.     boot_save2log();
  244.     /* Specification: askrunlevel / time & cmos
  245.         askrunlevel grab the time from cmos right at boot
  246.         time. The /sbin/clock command in most /etc/rc.d/rc.S
  247.         is useless.
  248.     */
  249.     datetime_getfromcmos();
  250.     modules_check();
  251.     dialog_settimeout (15,MENU_ESCAPE,true);
  252.     fstab_check();            // Check /etc/fstab 
  253.     fstab_checkmount(1);    // mount local filesystems
  254.     configf_booterase();    // some cleanup
  255.     fixperm_check_boot();    // check some permissions
  256.     askrunlevel_readparm (parm);
  257.     dialog_settimeout (0,MENU_ESCAPE,false);
  258.     // Conditionnally activate the timeout
  259.     // firsttime toggle the message about the timeout
  260.     int timeout = askrunlevel_enabletimeout (parm);
  261.     int choice = parm.defmode;
  262.     while (1){
  263.         static const char *set_config = MSG_U(M_TWORKSTATION,"the workstation");
  264.         static const char *boot_log = MSG_U(M_BOOTLOGS,"the boot logs");
  265.         static const char *menuopt[]={
  266.             MSG_U(M_START,"Start"),    NULL,
  267.             " ",        NULL,
  268.             " ",        NULL,
  269.             " ",        NULL,
  270.             " ",        NULL,
  271.             " ",        NULL,
  272.             MSG_R(M_CONFIG), set_config,
  273.             MSG_U(M_VIEW,"View"), boot_log,
  274.             NULL
  275.         };
  276.         char status_graphic[2000];
  277.         int graphic_ok = xconf_xok(status_graphic);
  278.         char status_net[2000];
  279.         int net_ok = netconf_netok(status_net) != NULL;
  280.         RUNLEVELS runlevels (graphic_ok,net_ok);
  281.         runlevels.setmenu (menuopt);
  282.         char infohelp[500];
  283.         strcpy (infohelp,MSG_U(I_SELONE
  284.             ,"Select one of the operation mode below\n"
  285.              "or configure the default mode"));
  286.         if (timeout != 0){
  287.             sprintf (infohelp+strlen(infohelp)
  288.                 ,MSG_U(I_WARN,"\n"
  289.                  "Unless you select something within %d seconds\n"
  290.                  "\"%s\" will start automaticly")
  291.                 ,timeout,menuopt[choice*2+1]);
  292.         }
  293.         timeout = 0;
  294.         MENU_STATUS code = xconf_menu (MSG_U(T_OPERMODE,"Operation mode")
  295.             ,infohelp
  296.             ,help_askrun
  297.             ,menuopt,choice);
  298.         if (code != MENU_OK){
  299.             runlevels.setlevel(parm.defmode);
  300.             break;
  301.         }else{
  302.             const char *key = menuopt[choice*2+1];
  303.             if (key == set_config){
  304.                 if (perm_checkpass()){
  305.                     linuxconf_main(1);
  306.                     askrunlevel_readparm (parm);
  307.                 }
  308.             }else if (key == boot_log){
  309.                 boot_showlog();
  310.             }else{
  311.                 RUNLEVEL *ptrun = runlevels.tbrun + choice;
  312.                 if (!ptrun->graphic_err && !ptrun->net_err){
  313.                     if (ptrun->init_runlevel != 'S'
  314.                         || perm_checkpass()){
  315.                         runlevels.setlevel(choice);
  316.                         break;
  317.                     }
  318.                 }else if (ptrun->graphic_err
  319.                     && ptrun->net_err){
  320.                     askrunlevel_saynographic_net(status_graphic,status_net);
  321.                 }else if (ptrun->graphic_err){
  322.                     askrunlevel_saynographic(status_graphic);
  323.                 }else{
  324.                     askrunlevel_saynonet(status_net);
  325.                 }
  326.             }
  327.         }
  328.     }
  329.     return 0;
  330. }
  331.  
  332.